package com.three.monitor;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * AOP实现度量记录
 * 方法访问指标
 * access：访问值
 * success：成功值
 * failure：失败值
 * Created by ziqingwang on 2017/1/5.
 */
@Aspect
@Component //注入依赖
public class MetricsAdvice {
    @Autowired
    private MetricsHelper metricsHelper;
    private static final Logger logger= Logger.getLogger(MetricsAdvice.class);
    private static String COUNT_ALL_FORMAT="method.access:%s";
    private static String COUNT_FAILURE_FORMAT="method.failure:%s";
    private static String COUNT_SUCCESS_FORMAT="method.success:%s";
    @Around("@annotation(metricsMethod)")
    private Object around(ProceedingJoinPoint pjp, MetricsMethod metricsMethod) throws Throwable{
        Object result=new Object();
        String value= metricsMethod.value();
        if(StringUtils.isEmpty(value)){
            //使用class.method
            value=pjp.getTarget().getClass().getName()+"."+pjp.getSignature().getName();
        }
        metricsHelper.increment(String.format(COUNT_ALL_FORMAT,value));
        try{
            //返回值被抛弃了！！！
            //pjp.proceed();
            result=pjp.proceed();
        }catch (Exception e){
            logger.error("MetricsAdvice error,msg:{}",e);
            metricsHelper.increment(String.format(COUNT_FAILURE_FORMAT,value));
            //错误参数记录
            Map<String,Object> traceDate= Maps.newHashMap();
            traceDate.put("timestamp",System.currentTimeMillis());
            traceDate.put("method",value);
            Map<String,Object> argsDate= Maps.newHashMap();
            argsDate=Stream.of(pjp.getArgs()).collect(Collectors.toMap(
                    i->i.getClass().getName(),
                    Function.identity()
            ));
            traceDate.put("args",argsDate);
            traceDate.put("exception",e);
            metricsHelper.addTraceData(traceDate);
        }
        metricsHelper.increment(String.format(COUNT_SUCCESS_FORMAT,value));
        return result;
    }
}
